﻿using StarryEdge.Core;
using StarryEdge.Core.Device;
using StarryEdge.Core.Models;
using StarryEdge.Core.Models.Interact;
using StarryEdge.Core.Models.Interact.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace StarryEdge.WPF.Attributes
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)]
    public class MemoryReadAttribute : Attribute
    {
        public MemoryReadAttribute()
        {
            
        }

        public bool Handle(IStarryEdgeLog starryEdgeLog, IDialogHost dialogHost, object obj, bool isCip, IDevice device)
        {
            if (isCip)
            {
                HandleContext<string> scanSignal_string = obj as HandleContext<string>;
                IPLC<string> plc_string = device as IPLC<string>;
                List<string> tags = new List<string>();
                for (int i = 0; i < scanSignal_string.Struct_Length; i++)
                {
                    tags.Add($"{scanSignal_string.Address_Struct}[{i}]");
                }
                for (int i = 0; i < 3; i++)
                {
                    List<BatteryModel> batterys = plc_string.Read<BatteryModel>(tags.ToArray(), 3)?.ToList() ?? new List<BatteryModel>();
                    if (batterys.Count > 0)
                    {
                        List<BatteryTaskModel<string>> batteryDatas = new List<BatteryTaskModel<string>>();
                        for (int j = 0; j < batterys.Count; j++)
                        {
                            if (batterys[j].ID != 0)
                            {
                                batteryDatas.Add(new BatteryTaskModel<string>()
                                {
                                    Index = (byte)(j + 1),
                                    Address_Struct = tags[j],
                                    SnowflakeId = batterys[j].ID,
                                    Data_PLC = batterys[j].Data_PLC,
                                });
                            }
                        }
                        if (batteryDatas.Count > 0)
                        {
                            scanSignal_string.BatteryTasks = batteryDatas;
                            return false;
                        }
                        if (i == 2 && batteryDatas.Count == 0)
                        {
                            WriteStingCMD(1, plc_string, "", starryEdgeLog);
                        }
                        Thread.Sleep(500);
                        return true;
                    }
                    else
                    {
                        starryEdgeLog.LogRun($"[{scanSignal_string.TaskName}] 记忆读取失败!!!", Core.Enums.LogLevel.Warning);
                    }
                }
            }
            else
            {
                HandleContext<int> scanSignal_int = obj as HandleContext<int>;
                IPLC<int> plc_int = device as IPLC<int>;
                for (int i = 0; i < 3; i++)
                {
                    List<BatteryTaskModel<int>> batteryIntDatas = new List<BatteryTaskModel<int>>();
                    BatteryArrayModel batterys = new BatteryArrayModel(scanSignal_int.Struct_Length);
                    var data_obj = plc_int.ReadClass(scanSignal_int.Address_Struct, batterys);
                    if (data_obj == null)
                    {
                        starryEdgeLog.LogRun($"读取记忆异常！！！", Core.Enums.LogLevel.Warning);
                        return true;
                    }
                    for (int j = 0; j < batterys.Batterys.Length; j++)
                    {
                        if (batterys.Batterys[j].ID != 0)
                        {
                            batteryIntDatas.Add(new BatteryTaskModel<int>()
                            {
                                Index = (byte)(j + 1),
                                Address_Struct = scanSignal_int.Address_Struct + ((scanSignal_int.AddressingMethod == "字节" ? 20 : 10) * j),
                                SnowflakeId = batterys.Batterys[j].ID,
                                Data_PLC = batterys.Batterys[j].Data_PLC,
                            });
                        }
                    }
                    if (batteryIntDatas.Count > 0)
                    {
                        scanSignal_int.BatteryTasks = batteryIntDatas;
                        return false;
                    }
                    if (i == 2 && batteryIntDatas.Count == 0)
                    {
                        WriteCMD(1, plc_int, 121325, starryEdgeLog);
                    }
                    Thread.Sleep(500);
                }
            }
            return true;
        }

        /// <summary>.
        /// 写入指令
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="devices">PLC链接</param>
        /// <param name="address">地址</param>
        public bool WriteCMD(ushort value, IPLC<int> devices, int address, IStarryEdgeLog starryEdgeLog)
        {
            for (int i = 0; i < 3; i++)
            {
                if (devices.WriteSingle(address, value, 0))
                {
                    starryEdgeLog.LogRun($"第[{i}]次 命令 [{value}] 写入成功", Core.Enums.LogLevel.Success);
                    return true;
                }
                else
                {
                    starryEdgeLog.LogRun($"第[{i}]次 命令 [{value}] 写入失败", Core.Enums.LogLevel.Warning);
                }
            }
            return false;
        }

        /// <summary>.
        /// CIP或OPC写入指令
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="devices">PLC链接</param>
        /// <param name="address">地址</param>
        public void WriteStingCMD(short value, IPLC<string> plc, string label, IStarryEdgeLog starryEdgeLog)
        {
            for (int i = 1; i < 4; i++)
            {
                if (plc.WriteSingle(label, 3, value))
                {
                    starryEdgeLog.LogRun($"Label [{label}] 写入数据 [{value}] 第[{i}]次写入成功", Core.Enums.LogLevel.Success);
                    return;
                }
                else
                {
                    starryEdgeLog.LogRun($"Label [{label}] 写入数据 [{value}] 第[{i}]次写入" +
                        $"失败", Core.Enums.LogLevel.Warning);
                }
            }
        }
    }
}
